#pragma once
#include "stdafx.h"
#include "Application.h"
#include "MonkeyScene.h"
#include "Menu.h"
#include <HSModel\World.h>
#include <HSModel\Picker.h>
#include <HSModel\WorldUpdater.h>
#include "SceneController.h"

#include <boost/optional/optional.hpp>

class Water;

class EventHandler
	{
	public:
    EventHandler(const std::string &i_name);

    virtual std::string GetName() const;
		virtual void MouseClick(const OIS::MouseEvent &evt, OIS::MouseButtonID id) = 0;
    virtual void MouseMove(const OIS::MouseEvent &evt) = 0;
    virtual void MouseUp(const OIS::MouseEvent &evt, OIS::MouseButtonID id) = 0;

    virtual ~EventHandler();

  private:
    std::string m_name;
	};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class CreateHillEventHandler : public EventHandler
  {
  private:
    Application& m_application;
    std::shared_ptr<Model3DRenderer> m_render_triangles;
    std::shared_ptr<Model3D>  mp_highlighted_model;
    bool is_valid;
  public:
    CreateHillEventHandler(Application& i_application);
		virtual void MouseClick(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
    virtual void MouseMove(const OIS::MouseEvent &evt) override;
    virtual void MouseUp(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
  private:
    void _ClickAction(const OIS::MouseEvent &evt, OIS::MouseButtonID id);
    void _MoveAction(const OIS::MouseEvent &evt);
  };

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class CreateHoleEventHandler : public EventHandler
  {
  private:
    Application& m_application;
    std::shared_ptr<Model3DRenderer> m_render_triangles;
    std::shared_ptr<Model3D>  mp_highlighted_model;
    bool is_valid;
  public:
    CreateHoleEventHandler(Application& i_application);
    virtual void MouseClick(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
    virtual void MouseMove(const OIS::MouseEvent &evt) override;
    virtual void MouseUp(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
  private:
    void _ClickAction(const OIS::MouseEvent &evt, OIS::MouseButtonID id);
    void _MoveAction(const OIS::MouseEvent &evt);

  };

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class CreateWaterEventHandler : public EventHandler
  {
  public:
    CreateWaterEventHandler(Application& i_application);
    virtual void MouseClick(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
    virtual void MouseMove(const OIS::MouseEvent &evt) override;
    virtual void MouseUp(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
  private:
    void _InitPicker();
  private:
    Application& m_application;
    std::vector<std::shared_ptr<Water>> m_models;
    std::vector<std::shared_ptr<Model3DRenderer>> m_renderers;
    Picker m_picker_highlighted;
    Picker m_picker_water;
    boost::optional<size_t> m_highlighted_index;
    std::shared_ptr<Model3DRenderer> mp_highlighting_renderer;
    std::shared_ptr<Model3D> mp_highlighted_model;
  };

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class AddWalkwayEventHandler : public EventHandler
  {
  private:
    Application& m_application;
    std::shared_ptr<Model3DRenderer> m_render_triangles;
    std::shared_ptr<Model3D>  mp_highlighted_model;
    bool m_is_mouse_button_pressed;
  public:
    AddWalkwayEventHandler(Application& i_application);
    virtual void MouseClick(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
    virtual void MouseMove(const OIS::MouseEvent &evt) override;
    virtual void MouseUp(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
  };

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class AddGrassEventHandler : public EventHandler
  {
  private:
    Application& m_application;
    std::shared_ptr<Model3DRenderer> m_render_triangles;
    std::shared_ptr<Model3D>  mp_highlighted_model;
    bool m_is_mouse_button_pressed;
  public:
    AddGrassEventHandler(Application& i_application);
    virtual void MouseClick(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
    virtual void MouseMove(const OIS::MouseEvent &evt) override;
    virtual void MouseUp(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
  };

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class AddTreeEventHandler : public EventHandler
  {
  private:
    Application& m_application;
    std::shared_ptr<Model3DRenderer> mp_model_renderer;
    std::shared_ptr<Model3DRenderer> mp_cell_renderer;
  public:
    AddTreeEventHandler(Application& i_application);
    virtual void MouseClick(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
    virtual void MouseMove(const OIS::MouseEvent &evt) override;
    virtual void MouseUp(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
  };

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class AddFerrisWheelEventHandler : public EventHandler
  {
  private:
    Application& m_application;
    std::shared_ptr<Model3DRenderer> mp_model_renderer;
    std::shared_ptr<Model3DRenderer> mp_cell_renderer;
  public:
    AddFerrisWheelEventHandler(Application& i_application);
    virtual void MouseClick(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
    virtual void MouseMove(const OIS::MouseEvent &evt) override;
    virtual void MouseUp(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
  };

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class AddBalloonsShopEventHandler : public EventHandler
  {
  private:
    Application& m_application;
    std::shared_ptr<Model3DRenderer> mp_model_renderer;
    std::shared_ptr<Model3DRenderer> mp_cell_renderer;
  public:
    AddBalloonsShopEventHandler(Application& i_application);
    virtual void MouseClick(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
    virtual void MouseMove(const OIS::MouseEvent &evt) override;
    virtual void MouseUp(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
  };
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class AddBenchEventHandler: public EventHandler
  {
  private:
    Application& m_application;
    std::shared_ptr<Model3DRenderer> mp_model_renderer;
    std::shared_ptr<Model3DRenderer> mp_cell_renderer;
  public:
    AddBenchEventHandler(Application& i_application);
    virtual void MouseClick(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
    virtual void MouseMove(const OIS::MouseEvent &evt) override;
    virtual void MouseUp(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
  };

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class DestroyObjectsEventHandler : public EventHandler
  {
  public:
    DestroyObjectsEventHandler(Application& i_app);
    virtual void MouseClick(const OIS::MouseEvent& evt, OIS::MouseButtonID id) override;
    virtual void MouseMove(const OIS::MouseEvent& evt) override;
    virtual void MouseUp(const OIS::MouseEvent &evt, OIS::MouseButtonID id) override;
  private:
    void _InitializePicker();
  private:
    Application& m_application;
    std::shared_ptr<Model3DRenderer> mp_render_triangles;
    Picker m_picker;
    std::shared_ptr<Model3D>  mp_highlighted_model;
    boost::optional<size_t> m_water_index;
  };
